/*
 *=================================================
 *	Server.cpp 
 *	Source Revision Date : 2007-02-09
 *	Source Revision By : KyungTaek, Lim
 *	Revision History:
 *		(2007-01-31)
 *		1. 서버 모듈 붙임.
 *		(2007-02-09)
 *		1. Optimizer 붙임.
 *		2. 클라이언트 요청시 동작 수정 및 추가
 *		(2007-02-12)
 *		1. LinkPump 추가.
 *		
 *==================================================
 */ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "Server.h"
#include "XML_Generator.h"
#include "Date.h"

using namespace std;
using namespace userDate;

#define SEND_FILE_BY_MACADDRESS    	10000001
#define NOT_FOUND_MACADDRESS        10000002
#define NOT_FOUND_BOOKMARK          10000003

#define SEND_FILE_BY_URL            10000004
#define NOT_FOUND_URL               10000005

#define SEND_FILE_BY_TAG            10000006
#define NOT_FOUND_TAG               10000007

#define ADD_TAG_SUCCESS             10000008
#define ADD_TAG_FAILED              10000009

// Client >> Server Message
#define CHECK_MACADDRESS            20000001
#define CHECK_URL                   20000002
#define CHECK_TAG                   20000003
#define CHECK_ADD_TAG               20000004

#define BUFFERSIZE					32768	

char fileDataBuffer[BUFFERSIZE];

Server::Server() 
{	
	this->port = 1092;
	
	this->userMGR			 = new UserMGR;
	this->channelMGR 	 	 = new ChannelMGR;
	this->tagMGR 			 = new TagMGR;
	this->itemMGR 			 = new ItemMGR( this->channelMGR, this->tagMGR );
	this->rssDocumentLinkMGR = new RSSDocumentLinkMGR;
	this->rssRefresher 		 = new RSSRefresher( this->channelMGR, this->itemMGR, this->tagMGR );
	this->clientMGR 		 = new ClientMGR;
	this->optimizer			 = new Optimizer;

	if ( pthread_mutex_init ( &socket_mutx, NULL ) &&
		 pthread_mutex_init ( &allMgr_mutx, NULL ) )
	{
		    perror( "thread mutex init error.");
	};
	
}

Server::Server ( int port, 
				 UserMGR* userMGR, ChannelMGR* channelMGR, ItemMGR* itemMGR, TagMGR* tagMGR,
        		 RSSDocumentLinkMGR* rssDocumentLinkMGR, RSSRefresher* rssRefresher, ClientMGR* clientMGR, Optimizer* optimizer )
{
	this->port 		 		 = port;

	this->userMGR			 = userMGR;
	this->channelMGR		 = channelMGR;
	this->itemMGR			 = itemMGR;
	this->tagMGR			 = tagMGR;
	this->rssDocumentLinkMGR = rssDocumentLinkMGR;
	this->rssRefresher		 = rssRefresher;
	this->clientMGR			 = clientMGR;
	this->optimizer			 = optimizer;
}


Server::Server( const Server& source )
{
	this->port = source.port;
	
	this->userMGR            = source.userMGR;
	this->channelMGR         = source.channelMGR;
	this->itemMGR            = source.itemMGR;
	this->tagMGR             = source.tagMGR;
	this->rssDocumentLinkMGR = source.rssDocumentLinkMGR;
	this->rssRefresher       = source.rssRefresher;
	this->clientMGR          = source.clientMGR;
	this->serverSocket		 = source.serverSocket;
	this->optimizer			 = source.optimizer;
}

Server::~Server()
{
	delete this->userMGR;
	delete this->channelMGR;
	delete this->itemMGR;
	delete this->tagMGR;
	delete this->rssDocumentLinkMGR;
	delete this->rssRefresher;
	delete this->clientMGR;
	delete this->optimizer;
	
}

//Operator = : 치환 연산자
Server& Server::operator = ( const Server& source )
{
	this->port 				 = source.port;
	this->userMGR            = source.userMGR;
	this->channelMGR         = source.channelMGR;
	this->itemMGR            = source.itemMGR;
	this->tagMGR             = source.tagMGR;
	this->rssDocumentLinkMGR = source.rssDocumentLinkMGR;
	this->rssRefresher       = source.rssRefresher;
	this->clientMGR          = source.clientMGR;
	this->serverSocket		 = source.serverSocket;
	this->optimizer			 = source.optimizer;

	return (*this);
}

//General Function ///////////////////////////////////////////////////////////////////////////


// XML Generate		
string& Server::XmlGenerate( string filename, int itemCount, Item* itemSet, Tag* keyWord )
{

	FILE* rss;
	RecordRSS( rss, filename, itemCount, itemSet, keyWord );
	
	return const_cast<string&>( filename );
}

												

// Network Function : Transfer()
void Server::Transfer()
{
	//서버 소켓 생성
	this->serverSocket = new PSocket ( PF_INET, SOCK_STREAM, 0 );
	
	//스레드 변수 선언
	pthread_t thread;

	// 서버 소켓에 주소 및 포트 정보 할당
	this->serverSocket->Bind( AF_INET, this->port );

	//연결 요청 대기
	this->serverSocket->Listen( 100 );	//최대 동시접속자 : 100개 

	//연결 요청이 왔을 경우 진행됨.
	while (1)
	{
		//새로운 소켓 생성
		PSocket* clientSocket = new PSocket( PF_INET, SOCK_STREAM, 0 );

		//연결 수락.
		cout << ">> Server wating..."<< endl;
		this->serverSocket->Accept( clientSocket );
		cout << ">> Connected Client!" << endl;
		
		//임계영역 보호를 위한 뮤텍스 잠금
		pthread_mutex_lock ( &socket_mutx );

		// Record ( IP Address, client Socket )
		Client* client;	//새로운 클라이언트 생성
		
		client = this->clientMGR->Record ( clientSocket, inet_ntoa ( clientSocket->GetSocketAddress().sin_addr ) );

		// 임계 영역 보호를 위한 뮤텍스 해제
		pthread_mutex_unlock ( &socket_mutx  );

		//스레드 함수에 넘길 전달 인자를 생성함. 전달할 인자가 많으므로 구조체로 생성되어있음. ( 헤더 파일 )
		Arg* arg = new Arg;
		arg->thisClient = client;		// 클라이언트 소켓
		arg->thisServer = this;			// 서버

		// 스레드 생성 및 함수 호출
//		pthread_mutex_lock ( &allMgr_mutx );
		pthread_create ( &thread, NULL, TF_ClntConnection, (void*)arg );	//arg는 방금 위에서 생성한 구조체 Arg형 arg임.
		
		printf(">> New Connect ( Client : %s ) \n", inet_ntoa( clientSocket->GetSocketAddress().sin_addr ) );

		void* t_return;
//		pthread_join( thread, &t_return );	//소멸
//		delete this->serverSocket;
	}
}

void Server::Refresher()
{
	pthread_t thread;
	Arg* arg = new Arg;
	
	arg->channelMGR 		= this->channelMGR;
	arg->itemMGR			= this->itemMGR;
	arg->userMGR			= this->userMGR;
	arg->rssDocumentLinkMGR = this->rssDocumentLinkMGR;
	arg->rssRefresher		= this->rssRefresher;

	pthread_create( &thread, NULL, TF_RSSRefresher, (void *)arg );
	
}

void Server::LinkLoader()
{
	pthread_t thread;

	pthread_create( &thread, NULL, TF_LinkLoader, (void *)(this->rssDocumentLinkMGR) );
}


// Thread Function! /////////////////////////////////////////////////////////////////////////////////////////////

// Thread Function! : ClntConnectsion 
void* TF_ClntConnection( void* arg_ )
{
	Arg* arg = (Arg*)arg_;	

	TransferMessage transferMessage;
	memset ( &transferMessage, 0 , sizeof( TransferMessage ) );

	cout << ">>Data incomming.";
	arg->thisClient->GetClientConnectSocket()->Read( &transferMessage, sizeof(TransferMessage) );
	
	while ( transferMessage.type != CHECK_MACADDRESS &&
			transferMessage.type != CHECK_URL		 &&
			transferMessage.type != CHECK_TAG		 &&
			transferMessage.type != CHECK_ADD_TAG	 )
	{
		printf(".");
		arg->thisClient->GetClientConnectSocket()->Read( &transferMessage, sizeof(TransferMessage) );
	}
	printf("...Complited!\n");
	printf(">> Received Data Information : [ Data type: %d ] [ MSG : %s ] \n", transferMessage.type, transferMessage.contents );

	//수신된 메시지의 종류에 따라 동작을 달리한다.
	
	Tag** findedTag;
	Item* findedItem;

	unsigned int tagCount = 0;
	unsigned int itemCount = 0;
	int fileCount = 0;
	
	//임계영역 잠금.
	cout << ">> Mutex allMgr_mutx will Lock " << endl;
	pthread_mutex_lock ( &allMgr_mutx );
	printf(">> allMgr Locked : in Transfer thread function.\n");


	switch( transferMessage.type )
	{	
		case CHECK_MACADDRESS :
			{
				cout << ">> Enter case CHECK_MACADDRESS. " << endl;
				//클라이언트가 서버에게 맥 어드레스를 보내왔을 때
				//북마크에 등록된 태그별로 RSS 문서를 만들어 장치에 압축하여 보낸다.
				//arg->thisServer->GetClientMGR()->OnCheckMacAddress ( arg->thisClient, transferMessage );
				
				UserInformation* findedUser = (arg->thisServer->GetUserMGR())->Find ( transferMessage.contents );
				
				//사용자가 찾아졌을 경우,
				if ( findedUser != NULL )
				{
					cout << ">> Finded User: " << findedUser->GetEmailAddress() << "/ MAC Address:" << findedUser->GetmacAddress() << endl;
					//등록된 태그를 가져온다.
					(arg->thisServer->GetUserMGR())->Find ( findedUser, &tagCount, &findedTag );

					

					//찾아진 관심태그가 있을 경우
					if ( tagCount > 0 )
					{
						cout << ">> Finded Bookmark. Count: " << tagCount << endl;
						//파일 이름 구조체를 생성한다.
						string* fileName = new string[ tagCount ];
						
						for ( int i = 0; i < tagCount; i++ )
						{
							//cout << (findedTag[i])->GetTitle() << endl;
							//cout << ">> FindedTag:" << (findedTag[i])->GetTitle() << endl;
							//아이템을 찾아온다. 현재 이 부분에서 DB에서 찾아오지 못해 에러난다. 택한과 상의해봐야 함.
							(arg->thisServer->GetItemMGR())->Find( (findedTag[i]), &itemCount, &findedItem );

							if ( itemCount > 0 )
							{
								cout << ">> Find success item("<< itemCount << ") have this tag(" << ((findedTag)[i])->GetTitle() <<")" <<endl;
								//파일명을 저장한다.
								fileName[ fileCount ]  = transferMessage.contents;
								fileName[ fileCount ] += "_";
								fileName[ fileCount ] += (findedTag[i])->GetTitle();
								fileName[ fileCount ] += ".xml";	//XMLGenerator가 자동으로 안붙여주네. 철호형하고 그렇게 하기로 합의했었음.
								cout << ">> XML file name setting OK : " << fileName << endl;
								//파일을 생성한다.
								(arg->thisServer)->XmlGenerate( fileName[ fileCount ], itemCount, findedItem, findedTag[i] );
								fileCount++;
								cout << ">> " << fileName << "(" << fileCount << ")" << " generated now." << endl;
							}
							else 
							{
								printf(">> 태그[ %s ]에 관한 아이템이 존재하지 않습니다.\n", (findedTag[i])->GetTitle().c_str() );
							}
						}
						printf(">> 최종 생성된 문서 개수: %d \n", fileCount );
						
						
						//RSSLIST.dat 파일을 생성하는 부분
						FILE* file = fopen( "RSSLIST.dat", "wt");
						
						for ( int l = 0; l < fileCount; l++ )
						{
							char fileStruct[256] = "";
							strncpy ( fileStruct, fileName[l].c_str(), 256 );

							fprintf( file, "%s\n", fileStruct );
						}
						fprintf( file, "\n" );
						fclose( file );


						string compCommand = "tar -zcvf ";

						compCommand += transferMessage.contents;
						compCommand += ".tar.gz ";
						compCommand += transferMessage.contents;
						compCommand += "*";
						compCommand += " RSSLIST.dat";
						compCommand += " *.png";


						int compFlag = system ( compCommand.c_str() );
						//if ( compFlag == 0 )	//압축파일이 정상적으로 생성되었다면,
						//{
							// 압축 파일의 권한을 변경한다.
							compCommand = "chmod 777 ";
							compCommand += transferMessage.contents;
							compCommand += ".tar.gz";
							system( compCommand.c_str() );
							
							// Network 전송하는 부분 시작!
							// 이부분은 ClientMGR.cpp에서 발췌함.
							int len = 0;
							string compFileName = transferMessage.contents;
							compFileName += ".tar.gz";
							//삭제할 명령을 미리 만들어둔다.
							
							string rmCommand = "rm -f ";
							rmCommand += transferMessage.contents;
							rmCommand += "*";
							
							system( "rm *.png" );

							int fd = open ( compFileName.c_str() , O_RDONLY );

							if ( fd == -1 )	printf ( ">> File Open Error : %s \n", compFileName.c_str() );

							else
							{
								//printf(">> Transfer f                                memset( fileDataBuffer, 0, sizeof(fileDataBuffer) );
								//                                while( (len = read( fd, fileDataBuffer, sizeof(fileDataBuffer) ) ) != 0 )
								//                                                                {
								//                                                                                                    arg->thisClient->GetClientConnectSocket()->Write( fileDataBuffer, len );
								//                                                                                                                                        printf("%s", fileDataBuffer );
								//                                                                                                                                                                            printf(".");
								//                                                                                                                                                                                                            }
								//                                                                                                                                                                                                             ile...");
								transferMessage.type = SEND_FILE_BY_MACADDRESS;
								strcpy( transferMessage.contents, "" );
								arg->thisClient->GetClientConnectSocket()->Write( &transferMessage, sizeof(TransferMessage) );
								cout<<"Here?"<<endl;							
								//cout << ">> fd:" << fd << "  / sizeof contents" << sizeof(transferMessage.contents) << endl;
								memset( fileDataBuffer, 0, sizeof(fileDataBuffer) );							
								while( (len = read( fd, fileDataBuffer, sizeof(fileDataBuffer) ) ) != 0 )
								{
									arg->thisClient->GetClientConnectSocket()->Write( fileDataBuffer, len );
									printf("%s", fileDataBuffer );
									printf(".");
								}
								//printf("Finished!\n");

							}

							close( fd );
							system ( rmCommand.c_str() );

							arg->thisClient->GetClientConnectSocket()->Close();
						//}
					}
					else 
					{
						printf(">>등록된 북마크가 없습니다.\n");

						//장치에게 등록된 북마크가 없음을 알린다.
						transferMessage.type = NOT_FOUND_BOOKMARK;
						strcpy ( transferMessage.contents, "" );
						arg->thisClient->GetClientConnectSocket()->Write( &transferMessage, sizeof( transferMessage ) );
					}			
				}
				else
				{
					printf(">>등록된 사용자가 아닙니다. \n");
					
					//장치에게 등록된 장치가 아님을 알린다.
					transferMessage.type = NOT_FOUND_MACADDRESS;
					strcpy ( transferMessage.contents, "" );
					arg->thisClient->GetClientConnectSocket()->Write( &transferMessage, sizeof( transferMessage ) );
				}
				
				break;
			}// case CHECK_MACADDRESS END!
			
		case CHECK_URL :
			{
				//클라이언트가 서버에게 컨텐츠의 URL을 보내왔을 때
				//해당 웹페이지를 다운로드받아서 옵티마이징 한 후 장치에 압축하여 보낸다.
				//arg->thisServer->GetClientMGR()->OnCheckURL( arg->thisClient, transferMessage );

				// sleep(2);	// Thread 안정성을 위해 추가함. 지우지 말 것.
	
				Item findedItem = arg->thisServer->GetItemMGR()->Find ( transferMessage.contents );

				//Item이 정상적으로 찾아졌으면, 
				if ( findedItem.GetTitle() != "" )
				{
					arg->thisServer->GetOptimizer()->SetSearchKey( findedItem.GetLink() );		//추천 리턴: string으로 템플릿 이름
					arg->thisServer->GetOptimizer()->ReadDescription( findedItem.GetTitle() );		//추천 리턴: 성공/실패
					arg->thisServer->GetOptimizer()->RemoveUnessentialTag();				
					arg->thisServer->GetOptimizer()->RenderingImage();
					arg->thisServer->GetOptimizer()->FilteringEmbedTag();
					arg->thisServer->GetOptimizer()->MakeHtmlDocument();
					bool successFlag = arg->thisServer->GetOptimizer()->MakeSendingZipFile();

					if ( successFlag )
					{
						int len = 0;
						int fd = open ( "item.tar.gz" , O_RDONLY );

						if ( fd == -1 ) printf ( ">> File Open Error : item.tar.gz \n" );
						else
						{
							printf(">> Transfer file...");
							transferMessage.type = SEND_FILE_BY_URL;
							strcpy ( transferMessage.contents, "" );

							arg->thisClient->GetClientConnectSocket()->Write( &transferMessage, sizeof( transferMessage) );

							memset( fileDataBuffer, 0, sizeof(fileDataBuffer) );
							while ( ( len = read ( fd, fileDataBuffer, sizeof ( fileDataBuffer ) ) ) != 0 )
							{
								arg->thisClient->GetClientConnectSocket()->Write( fileDataBuffer, len );
								printf(".");
							}
							printf("Finished!\n");
						}
						// 전송 후 남아있는 압축파일 삭제
			//			arg->thisServer->GetOptimizer()->RemoveSendedZipFile();
					}
					else
					{
						cout << ">> URL Comp.File Create Failed. " << endl;

						printf(">> Transfer file...");
						transferMessage.type = NOT_FOUND_URL;
						strcpy ( transferMessage.contents, "" );

						arg->thisClient->GetClientConnectSocket()->Write( &transferMessage, sizeof(transferMessage) );

					}
				}
				else
				{
					cout << ">> [" << transferMessage.contents <<"]를 가진 아이템이 검색되지 않았습니다." << endl;
					transferMessage.type = NOT_FOUND_URL;
					strcpy ( transferMessage.contents, "" );
					arg->thisClient->GetClientConnectSocket()->Write( &transferMessage, sizeof( transferMessage ) );
				}
				break;
			}// CHECK_URL END
			
		case CHECK_TAG :
			{
				//클라이언트가 서버에게 태그를 보내왔을 때
				//태그에 해당하는 아이템으로 RSS 문서를 만들어 장치에 압축하여 보낸다.
				//arg->thisServer->GetClientMGR()->OnCheckTAG( arg->thisClient, transferMessage );

				// sleep(2);   // Thread 안정성을 위해 추가함. 지우지 말 것.
				
				string fileName;

				//일단, 해당 태그가 있는지 찾는다.
				Tag* findedTag = (arg->thisServer->GetTagMGR())->Find( transferMessage.contents );

				if ( findedTag != NULL )
				{
					//태그가 있을 경우 해당 태그를 가진 아이템을 찾는다.
					(arg->thisServer->GetItemMGR())->Find( findedTag, &itemCount, &findedItem );

					if ( itemCount > 0 )
					{
						//파일명을 저장한다.
						fileName = findedTag->GetTitle();
						
#if 0
						int emptyPos = 0;

						// 파일명에 공백이 있다면 '_'로 대체한다...
						while( ( emptyPos = fileName.find(" ") ) != -1 )
						{
							// fileName[emptyPos] = '_';
							fileName.erase(emptyPos, 1);
						}
#endif
												
						fileName += ".xml";
												
						(arg->thisServer)->XmlGenerate( fileName, itemCount, findedItem, findedTag );

						string compCommand = "tar -zcvf ";

						compCommand += fileName;
						compCommand += ".tar.gz ";
						compCommand += fileName;
						

						int compFlag = system ( compCommand.c_str() );

						cout << "compFlag = " << compFlag << endl;
						
						if ( compFlag == 0 )    //압축파일이 정상적으로 생성되었다면,
						{
							//압축 파일의 권한을 변경한다.
							compCommand = "chmod 777 ";
							compCommand += fileName;
							compCommand += ".tar.gz";
							system( compCommand.c_str() );

							//네트워크 전송 부분
							int len = 0;
							string compFileName = fileName;
							compFileName += ".tar.gz";
							int fd = open ( compFileName.c_str(), O_RDONLY );

							if ( fd == -1 ) printf ( ">> File Open Error : %s \n", compFileName.c_str() );

							else
							{
								printf(">> Transfer file...");

								memset( &transferMessage, 0, sizeof(transferMessage) );
								
								transferMessage.type = SEND_FILE_BY_TAG;
								// 파일명을 전송한다.
								strcpy( transferMessage.contents, fileName.c_str() );
								
								cout << fileName << endl;
								cout << transferMessage.contents << endl;
								
								arg->thisClient->GetClientConnectSocket()->Write( &transferMessage, sizeof(transferMessage) );
								
								memset( fileDataBuffer, 0, sizeof(fileDataBuffer) );
								while ( ( len = read ( fd, fileDataBuffer, sizeof (fileDataBuffer) ) ) != 0 )
								{
									arg->thisClient->GetClientConnectSocket()->Write( fileDataBuffer, len );
									printf(".");
								}
								printf("Finished!\n");
								
								string rmCommand = "rm -f ";
								rmCommand += fileName;
								rmCommand += "*";

								close( fd );
								system ( rmCommand.c_str() );

								arg->thisClient->GetClientConnectSocket()->Close();
							}
						}

					}
					else
					{
						printf(">> 태그[ %s ]에 관한 아이템이 존재하지 않습니다.\n", findedTag->GetTitle().c_str() );

						//장치에게 아이템이 검색되지 않았음을 알림.
						transferMessage.type = NOT_FOUND_TAG;
						strcpy ( transferMessage.contents, "" );
						arg->thisClient->GetClientConnectSocket()->Write( &transferMessage, sizeof( transferMessage ) );
					}
					//아이템이 검색되지 않았음을 알리는 시그널을 클라이언트 측에 보내야 할 것.
					/*else
					{
						 printf(">> 태그[ %s ]에 관한 아이템이 존재하지 않습니다.\n", findedTag->GetTitle().c_str() );

						  //장치에게 아이템이 검색되지 않았음을 알림.
						  transferMessage.type = NOT_FOUND_TAG;
						  strcpy ( transferMessage.contents, "" );
						  arg->thisClient->GetClientConnectSocket()->Write( &transferMessage, sizeof( transferMessage ) );
					}*/
				}
				else
				{
					printf(">> 해당 태그가 Database에 없습니다. \n" );
					
					//장치에게 태그가 검색되지 않았음을 알림.
					transferMessage.type = NOT_FOUND_TAG;
					strcpy ( transferMessage.contents, "" );
					arg->thisClient->GetClientConnectSocket()->Write( &transferMessage, sizeof( transferMessage ) );
				}
				break;
			}// Check Tag END
		

		case CHECK_ADD_TAG:
			{
				char macAddress[13] = "";
				string tag = transferMessage.contents + 12;
				strncpy ( macAddress, transferMessage.contents, 12 );

				UserInformation* user = arg->thisServer->GetUserMGR()->Find ( macAddress );

				//사용자가 찾아졌을 경우,
				if ( user != NULL )
				{
					cout << ">> user finded" << endl;
					BookMarkList* bookmarkList = user->GetBookMarkList();
					if ( bookmarkList != NULL ) 
					{
						cout << ">> finded bookmark" << endl;
						Tag* findedTag = arg->thisServer->GetTagMGR()->Find ( tag );
						//해당 태그가 찾아졌을 경우,
						if ( findedTag != NULL )
						{
							cout << ">> finded Tag" << endl;
							BookMark* temp = new BookMark( findedTag );
							BookMark* addResult = bookmarkList->TakeIn ( temp );

							delete temp;

							if ( addResult != NULL )
							{
								cout << ">> addTag success" << endl;
								//정상적으로 태그가 추가되었다면, 소켓을 열어 전송한다.
								transferMessage.type = ADD_TAG_SUCCESS;
								strcpy ( transferMessage.contents, "" );
								arg->thisClient->GetClientConnectSocket()->Write ( &transferMessage, sizeof(transferMessage) );
							}
							else
							{
								cout << ">> " << tag << "를 북마크에 추가하지 못했습니다." << endl;
								transferMessage.type = ADD_TAG_FAILED;
								strcpy ( transferMessage.contents, "" );
								arg->thisClient->GetClientConnectSocket()->Write ( &transferMessage, sizeof(transferMessage) );
							}
						}
						else
						{
							cout << ">>[" << tag <<  "]를 태그 목록에서 찾을 수 없습니다. 올바른 태그가 아닙니다." << endl;
							transferMessage.type = ADD_TAG_FAILED;
							strcpy ( transferMessage.contents, "" );
							arg->thisClient->GetClientConnectSocket()->Write ( &transferMessage, sizeof(transferMessage) );
						}
					}
					else
					{
						cout << ">> [" << user->GetEmailAddress() << "]에 등록된 북마크를 읽어오지 못했습니다." << endl;
						transferMessage.type = ADD_TAG_FAILED;
						strcpy ( transferMessage.contents, "" );
						arg->thisClient->GetClientConnectSocket()->Write ( &transferMessage, sizeof(transferMessage) );
					}
				}
				else 
				{
					cout << ">> 사용자를 찾을 수 없습니다." << endl;
					transferMessage.type = ADD_TAG_FAILED;
					strcpy ( transferMessage.contents, "" );
					arg->thisClient->GetClientConnectSocket()->Write ( &transferMessage, sizeof(transferMessage) );
				}
					
				break;
			}// Check Add Tag
			
		default :
			{
				printf(">> Warning!! transferMessage.type is not defined. \n");
				break;
			}
	}
	int index = arg->thisServer->GetClientMGR()->FindClient( arg->thisClient );

	printf( "[%d]\n", index );

	arg->thisServer->GetClientMGR()->DisConnectClient( index );
	pthread_mutex_unlock ( &allMgr_mutx );       //UnLock Mutex
	pthread_mutex_unlock ( &socket_mutx );		 //UnLock Mutex
	printf(">> allMgr & socket Unlocked : in Transfer thread function.\n");
	arg->thisClient->GetClientConnectSocket()->Close();

	delete arg;
}


// Thread Function! : RSS Document Refresher
void* TF_RSSRefresher( void* arg_ )
{
	printf(">> into the RSSRefresher thread function\n");
	
	Server* 			thisServer  = ((Arg*)arg_)->thisServer;
	ChannelMGR* 		chMgr 		= ((Arg*)arg_)->channelMGR;
	ItemMGR*			itemMgr 	= ((Arg*)arg_)->itemMGR;
	TagMGR*				tagMgr		= ((Arg*)arg_)->tagMGR;
	RSSDocumentLinkMGR* linkMgr 	= ((Arg*)arg_)->rssDocumentLinkMGR;
	RSSRefresher*		refresher	= ((Arg*)arg_)->rssRefresher;


	while ( 1 )
	{
		userDate::Date refreshDate;
		refreshDate.Update();

		cout << endl << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Update Time" << (char *)refreshDate << endl << endl;
		sleep ( 2 );
		printf(">> into the while loop.\n");		
		for ( int i = 0; i < linkMgr->GetLinkCount(); i++)
		{
			bool checkUpdate = false;

			if ( refresher->GetNetFile( &((*linkMgr)[i]) ) )
			{
				string templateName = refresher->SetTemplate();

				if( refresher->CheckUpdate(&( (*linkMgr)[i]) ) )
				{
					pthread_mutex_lock ( &allMgr_mutx );
					bool updateSuccess = refresher->Update( &( (*linkMgr)[i]) );
					pthread_mutex_unlock ( &allMgr_mutx );
				}
			}
		}
		sleep ( 15 );
	}
}


void* TF_LinkLoader( void* arg_ )
{
	RSSDocumentLinkMGR* rssDocumentLinkMGR = (RSSDocumentLinkMGR*)arg_;
	while (1)
	{
		cout << ">> Load RSS Link from DB. Plz wait...." << endl;
		pthread_mutex_lock( &allMgr_mutx );
		pthread_mutex_lock( &socket_mutx );

		rssDocumentLinkMGR->LoadDB();

		pthread_mutex_unlock ( &allMgr_mutx );
		pthread_mutex_unlock ( &socket_mutx );

		cout <<">> Load End. " << endl;
		
		sleep(120);
	}
		
}


// Main ///////////////////////////////////////////////////////////////////////////////////////////
#if 1
int main()
{
	Server* server = new Server;
	
	server->GetRSSDocumentLinkMGR()->LoadDB();
	server->GetChannelMGR()->LoadDB();
	server->GetTagMGR()->LoadDB();
//	server->GetUserMGR()->LoadDB();
	
/*
	server->GetRSSDocumentLinkMGR()->Record ( "http://uccviewer.tistory.com/rss",
//											  "http://uccviewer.tistory.com",
											  userDate::Date("Tue, 9 Aug 2006 16:15:02 GMT") );

	server->GetRSSDocumentLinkMGR()->Record ( "http://lohan.tistory.com/rss",
//											  "http://lohan.tistory.com/",
											   userDate::Date("Tue, 9 Aug 2006 16:15:02 GMT")  );
*/

//	server->GetRSSDocumentLinkMGR()->Record ( "http://rss.allblog.net/AllPosts.xml",
										 	 // "http://www.allblog.net/",
//											  userDate::Date("Tue, 9 Aug 2006 16:15:02 GMT") );
/*
	server->GetRSSDocumentLinkMGR()->Record ( "http://tmvlemaos.egloos.com/index.xml",
											 i// "http://blog.rss.naver.com/",
											   Date("Tue, 9 Aug 2006 16:15:02 GMT") );
*/	
	pthread_mutex_lock( &allMgr_mutx );


	//Server에서 태그를 찾아온다.

	BookMarkList* bookmarklist = new BookMarkList;	
	Tag* tag = server->GetTagMGR()->Find( "박컴" );
	BookMark* bookmark1 = new BookMark( tag );

//	tag = server->GetTagMGR()->Find( "▒ 얼리어댑터적사고 ▒" );
//	BookMark* bookmark2 = new BookMark( tag );

	tag = server->GetTagMGR()->Find("동영상");
	BookMark* bookmark3 = new BookMark( tag );
    tag = server->GetTagMGR()->Find("EPL");
	BookMark* bookmark4 = new BookMark ( tag );
	
	bookmarklist->TakeIn ( bookmark1 );
//	bookmarklist->TakeIn ( bookmark2 );
	bookmarklist->TakeIn ( bookmark3 );
	bookmarklist->TakeIn ( bookmark4 );
	
	tag = server->GetTagMGR()->Find( "휴대폰" );
	BookMark* bookmark5 = new BookMark( tag );
	
	tag = server->GetTagMGR()->Find( "비" );
	BookMark* bookmark6 = new BookMark( tag );
	
	tag = server->GetTagMGR()->Find("태터툴즈");
	BookMark* bookmark7 = new BookMark( tag );
	
	tag = server->GetTagMGR()->Find("졸업");
	BookMark* bookmark8 = new BookMark ( tag );
	
	bookmarklist->TakeIn ( bookmark5 );
	bookmarklist->TakeIn ( bookmark6 );
	bookmarklist->TakeIn ( bookmark7 );
	bookmarklist->TakeIn ( bookmark8 );

	tag = server->GetTagMGR()->Find( "News" );
	BookMark* bookmark9 = new BookMark( tag );

	tag = server->GetTagMGR()->Find( "이올린" );
	BookMark* bookmark10 = new BookMark( tag );

	tag = server->GetTagMGR()->Find("영화");
	BookMark* bookmark11 = new BookMark( tag );

	tag = server->GetTagMGR()->Find("애니메이션");
	BookMark* bookmark12 = new BookMark ( tag );

	bookmarklist->TakeIn ( bookmark9 );
	bookmarklist->TakeIn ( bookmark10 );
	bookmarklist->TakeIn ( bookmark11 );
	bookmarklist->TakeIn ( bookmark12 );

	tag = server->GetTagMGR()->Find( "발렌타인" );
	BookMark* bookmark13 = new BookMark( tag );
	bookmarklist->TakeIn ( bookmark13 );
	
#if 0	
	tag = server->GetTagMGR()->Find( "비행" );
	BookMark* bookmark14 = new BookMark( tag );

	tag = server->GetTagMGR()->Find("발렌타인");
	BookMark* bookmark15 = new BookMark( tag );
#if 0
//	tag = server->GetTagMGR()->Find("Apple");
//	BookMark* bookmark16 = new BookMark ( tag );

	bookmarklist->TakeIn ( bookmark13 );
	bookmarklist->TakeIn ( bookmark14 );
	bookmarklist->TakeIn ( bookmark15 );
	bookmarklist->TakeIn ( bookmark16 );
#endif

	tag = server->GetTagMGR()->Find( "안철수" );
	BookMark* bookmark17 = new BookMark( tag );
	
	tag = server->GetTagMGR()->Find( "낙서장" );
	BookMark* bookmark18 = new BookMark( tag );

	tag = server->GetTagMGR()->Find("어머니");
	BookMark* bookmark19 = new BookMark( tag );

	tag = server->GetTagMGR()->Find("블로그");
	BookMark* bookmark20 = new BookMark ( tag );

	bookmarklist->TakeIn ( bookmark17 );
	bookmarklist->TakeIn ( bookmark18 );
	bookmarklist->TakeIn ( bookmark19 );
	bookmarklist->TakeIn ( bookmark20 );


	tag = server->GetTagMGR()->Find( "컴퓨터" );
	BookMark* bookmark21 = new BookMark( tag );
	
	tag = server->GetTagMGR()->Find( "KTF" );
	BookMark* bookmark22 = new BookMark( tag );

	tag = server->GetTagMGR()->Find("맥북");
	BookMark* bookmark23 = new BookMark( tag );

	tag = server->GetTagMGR()->Find("KT");
	BookMark* bookmark24 = new BookMark ( tag );

	bookmarklist->TakeIn ( bookmark21 );
	bookmarklist->TakeIn ( bookmark22 );
	bookmarklist->TakeIn ( bookmark23 );
	bookmarklist->TakeIn ( bookmark24 );

	tag = server->GetTagMGR()->Find("추억");
	BookMark* bookmark25 = new BookMark ( tag );

	bookmarklist->TakeIn ( bookmark25 );
	
#endif
	UserInformation user( "indiweb@intotech.co.kr", "A0000000000A", "dreams", "lohan", bookmarklist );

	UserInformation* findedUser = server->GetUserMGR()->Record ( user );

	pthread_mutex_unlock ( &allMgr_mutx );	

	

	char flag[2] = "";

	while ( strcmp ( flag, "q" ) != 0 || strcmp ( flag, "Q" ) != 0 )
	{
		system ( "clear" );
		cout << endl << endl;
		cout << "***************************************************************************************************************"<< endl;
		cout << "   RSS Syndication Server v0.9 build 070213a										  "<< endl;
		cout << endl;
		cout << "   	copyright by Parkcom SE 145th OJT A Team									  "<< endl << endl;
		cout << "***************************************************************************************************************"<< endl;
		cout << "Server의 실행 형태를 선택하세요. ( 1: Only Refresh,  2: Only Transfer, 3: All 4: LinkLoader ) : ";

		scanf("%s", flag);

		if ( strcmp( flag, "1" ) == 0 )
		{
			server->LinkLoader();
			server->Refresher();
			gets(flag);
		}
		else if ( strcmp( flag, "2" ) == 0 )
		{
			server->LinkLoader();
			server->Transfer();
			gets(flag);
		}
		else if ( strcmp( flag, "3" ) == 0 )
		{
			server->LinkLoader();
			server->Refresher();
			server->Transfer();
			gets(flag);
		}
		else if ( strcmp( flag, "4" ) == 0 )
		{
			server->LinkLoader();
			gets(flag);
		}
	}
	
	return 0;
}
	
#endif

